Skip to content

Simplify reverse proxy hairpin NAT setup with host-gateway - #626

Open
pieterhollander wants to merge 1 commit into
netbirdio:mainfrom
pieterhollander:fix/reverse-proxy-host-gateway-v2
Open

Simplify reverse proxy hairpin NAT setup with host-gateway#626
pieterhollander wants to merge 1 commit into
netbirdio:mainfrom
pieterhollander:fix/reverse-proxy-host-gateway-v2

Conversation

@pieterhollander

Copy link
Copy Markdown

Replace static IP assignment for Traefik with Docker's built-in host-gateway, which is simpler and survives container restarts.

  • Replace static IP assignment for Traefik with Docker's built-in host-gateway, which is simpler and survives container restarts
  • Clarify what hairpin NAT is and how host-gateway avoids it
  • Remove the now-unnecessary static subnet/IP configuration and associated warning

Supersedes #609

Replace static IP assignment for Traefik with Docker's built-in
host-gateway, which is simpler and survives container restarts.
@TechHutTV

Copy link
Copy Markdown
Collaborator

Hey @pieterhollander, thanks for this one, and sorry it sat so long. Your instinct is right, the extra_hosts entry pointing at a hand-maintained IP is fragile, and your hairpin NAT explanation is clearer than what we have now. I want to land a version of this.

Two things came out of digging into it though.

First, we can't drop the static IP itself. In the quickstart stack, Traefik's fixed IP (172.30.0.10) is a security anchor. The management server only trusts forwarded client-IP headers from that exact IP (trustedHTTPProxies in management.json), and the proxy only accepts PROXY protocol headers from it (NB_PROXY_TRUSTED_PROXIES in proxy.env). If the IP goes dynamic, those trust rules silently break.

Second, host-gateway reaches Traefik through the published host port, so it depends on 443 being bound on an address containers can reach. Anyone publishing Traefik on a specific interface, or running strict DOCKER-USER firewall rules, gets a failure that's real hard to debug.

The good news is the fix ends up even simpler than host-gateway: keep the static IP, add a network alias, and delete extra_hosts entirely.

The section is now "Fix DNS resolution (same-host only)" on main, and the whole rework is about 20 lines:

  1. Rewrite the section intro around the alias (your hairpin explanation fits right in).
  2. In the yaml block, keep the networks/ipam config and the static IP, and add the alias:
  traefik:
    # ...existing traefik config...
    networks:
      netbird:
        ipv4_address: 172.30.0.10
        aliases:
          - "netbird.example.com"
  1. Delete the proxy extra_hosts snippet, nothing is needed on the proxy side anymore. Docker's embedded DNS resolves the domain for every container on the network.
  2. Replace the Warning at the bottom of the section. The silent-breakage failure mode is gone with extra_hosts, so it becomes a short note along the lines of: the static IP is still required because trustedHTTPProxies in management.json and NB_PROXY_TRUSTED_PROXIES in proxy.env trust Traefik by that exact address.

Steps 1 and 3 of the guide (gRPC route and idle timeout) stay untouched.

If you're up for that, I'm happy review any eidts. If you'd rather not after all this time, totally understand, say the word and I'll push the change myself and credit you for it. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants